iT邦幫忙

2026 iThome 鐵人賽

DAY 11
0
JavaScript

JS 核心重構:勇者轉職傳說系列 第 11

Day 10:原理篇 —— 【圖解】this 到底是誰?變色龍盔甲的指向判定法

  • 分享至 

  • xImage
  •  

本文同步分享於個人部落格:Liwen Chiou | Digital Architect & Full-Stack Engineer


📜 這裡的修煉規則:

孩子,在踏上今日的領地前,先坐下來喝杯酒吧。
修煉的路很長,別急著奔跑,先聽聽這份卷軸裡的古老叮嚀。

我在每一站的盡頭都為你鋪設了 實戰演武場 CodePen。那不只是程式碼的拼湊,而是你在這場暴風雨中,試圖用邏輯點燃的一顆星火。
成功突圍後,別忘了帶著你的戰利品回到 QuestBoard 佈告欄。在那裡,你會發現自己從不孤單,公會的夥伴們都正舉杯等待你的歸來。

記住...

導師看重的從來不是你的劍法有多華麗,而是當你被邏輯擊潰、滿身泥濘後,依然選擇握緊理性的劍柄,再次向真相發起衝鋒的勇氣。


🛡️ 【公會大廳:導師的修煉導讀】

「新夥伴,這套『變色龍盔甲 (this)』是公會最有名的聖物。它的神奇之處在於,它沒有固定的顏色,也沒有固定的主人。」我指著大廳中央那套發著微光的盔甲。

當戰士穿上它時,它就變成紅色且聽從戰士命令;當法師穿上它時,它就轉為藍色且聽從法師調遣。最尷尬的是,如果這套盔甲被隨便丟在地上沒人穿,它就會預設聽從「公會長 (Window)」的命令。很多冒險者會被 this 搞瘋,是因為他們在找「這段代碼寫在哪裡」,但其實你該找的是:「現在是誰在用它?」


💡 【導師講義:底層真相探究】

1. 變色龍判定法:誰呼叫,誰就是主人

在 JavaScript 的世界裡,this 的指向並不是在寫咒語時決定的,而是在 「發動咒語的瞬間(執行時)」 決定的。

判定三大金律:

  1. 物件調用:如果咒語前面有名號 obj.fn(),那麼點 . 前面的人就是主人。
    const warrior = {
      name: "艾冉",
      attack() {
        console.log(this.name);
      },
    };
    warrior.attack(); // 輸出:艾冉 (點前面是 warrior)
    
  2. 簡易呼叫:如果咒語前面沒人帶著,如 fn(),它就預設屬於最高領袖 (Window)。
    function shout() {
      console.log(this);
    }
    shout(); // 輸出:Window
    
  3. 箭頭函式 (Inheritance):還記得 Day 03 嗎?箭頭函式沒有自己的 this,它直接繼承 「宣告時外層環境」 的主人。

2. 強制認主:bind / call / apply

除了被動判定,我們也可以施展「契約魔法」來強制指定主人。

🏹 導師的辨析圖:契約魔法對照表

指令 動作說明 參數傳遞方式 是否立即執行
call() 強制指定主人並啟動 逐一傳入 (arg1, arg2) ✅ 是
apply() 強制指定主人並啟動 陣列傳入 ([args]) ✅ 是
bind() 簽訂專屬契約 預先綁定,不啟動 ❌ 否

3. 邏輯流向圖解

導師的圖解心法: this 會隨著它的 「持有者」 不同而變幻色澤。就像一把神劍,拿在勇者手上,它閃耀著正義之光(指向勇者物件);但如果神劍被掉在地上或被暴徒撿走,它的光芒就會隨之改變(指向新的執行環境)。決定光芒的,不是寶劍本身,而是 「誰在揮舞它」

變色龍盔甲指向圖


⚔️ 【戰術對抗:學長與學弟的代碼對決】

招式示範:看穿盔甲的主人

❌ 冒險學弟:自作多情的誤判

  • 負能量評級:🔴 丟失上下文 / 🔴 導致 undefined
const hero = {
  name: "辛梅爾",
  shout: function () {
    console.log(`🛡️ 勇者:${this.name}`);
  },
};

const talk = hero.shout; // ⚠️ 把咒語「單獨」儲存起來
talk(); // 輸出:🛡️ 勇者:undefined (因為 talk 前面沒點)

✅ 勇者學長:精準的靈魂鎖定 (Bind)

  • 利潤評級:🟢 邏輯嚴密 / 🟢 確保執行安全
const hero = {
  name: "辛梅爾",
  shout: function () {
    console.log(`🛡️ 勇者:${this.name}`);
  },
};

// 🔒 預約咒語時,透過 bind 強行指定主人為 hero
const talk = hero.shout.bind(hero);
talk(); // 輸出:🛡️ 勇者:辛梅爾 (門牌已鎖死!)

🏰 【勇者精英課:邁向職人的進階架構】

魔王的陷阱:回呼函式中的遺失

這是開發中最常出錯的地方。當你把物件的方法交給「計時器」或「事件監聽器」執行時,this 往往會變回空空如也的 Window

const mage = {
  name: "辛梅爾",
  greet() {
    setTimeout(function () {
      console.log(this.name); // 猜猜看是誰? (答案是:Window)
    }, 100);
  },
};

職人解法: 使用 Day 03 的箭頭函式,或者在此處進行 bind(this)。學會防止 this 遺失,是通往高階架構的必經之路。


🛖 【營火叮嚀:為什麼 this 總是讓你吐血?】

孩子,導師看過無數冒險者在處理「點擊事件」時,一用 this 就噴出錯誤。

「你沒帶它出門,它就不是你的。」 很多人以為在物件裡寫了 this,這輩子它就跟定你了。錯!如果你把這個咒語單獨交給別人(傳入外部函式執行),它就失去了原本宿主對它的控制。

記住:「如果你呼叫時失去了門牌號碼 (.),它的 this 就會瞬間易主。」


天色微亮,營火雖已燃盡,但你眼中卻閃爍著領悟的光芒。在前往演武場挑戰關卡前,我已經幫你把靈魂碎片精煉成了這份「戰術錦囊」。拿好它,今日的任務不再是負擔,而是你證明自我的舞台。去吧,公會的英雄榜在等著你的戰報。

📝 【夥伴筆記:今日修煉精華】

這份筆記是你的隨身護身符,卡關時看一眼,真相就在裡面。
  • 物件調用obj.fn()thisobj
  • 簡易調用fn()this 為預設領袖 (Window)。
  • 契約魔法:使用 call, apply, bind 強制決定歸屬。
  • 箭頭函式:沒有自己的主人,繼承宣告時的外層環境。

🎯 【實戰演武場】

⚔️ 任務鑑定條件:

  1. 完成 📜 本日實戰任務:變色龍盔甲判定實驗室 (CodePen)
  2. 將 CodePen 網址貼至 QuestBoard,並回填鑑定報告:
    • 初心者:主人識別術 (成就感發掘)
        1. 當你第一次發現「咒語脫離物件後會找不到主人」時,你有沒有感受到一種「必須明確主從關係」的理性訓練?
    • 冒險者:契約的力量 (理性挑戰)[⚡ 觀念辨析]
        1. 如果我們想讓一個傳入回呼函式的 this 乖乖聽話,除了 bind 之外,還會用哪招(Day 03 箭頭函式)?
  3. 任務完成後,你的名字將永遠標記在公會的英雄榜上!

📚 【圖書館卷軸:延伸學習】


上一篇
Day 09:原理篇 —— 陣列大戰:從傳統 for 到自動化生產線 map / filter
系列文
JS 核心重構:勇者轉職傳說11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言